using System;
using System.Configuration;
using System.Globalization;

namespace Be.Timvw.Framework
{
    /// <summary>
    /// Represents the environment for the application.
    /// </summary>
    public class ApplicationEnvironment : IApplicationEnvironment
    {
        #region Constants

        /// <summary>
        /// Appsettings key for the datetime format.
        /// </summary>
        public const string DateTimeFormatKey = "ApplicationDateTimeFormat";

        /// <summary>
        /// Appsettings key for the datetime value.
        /// </summary>
        public const string DateTimeValueKey = "ApplicationDateTimeValue";

        /// <summary>
        /// Default format string of the provided datetime value.
        /// </summary>
        public const string DefaultDateTimeFormat = "dd/MM/yyyy";

        #endregion

        #region Instance implementation

        /// <summary>
        /// The epoch of the application.
        /// </summary>
        private readonly DateTime applicationEpoch;

        /// <summary>
        /// The epoch of the current instance.
        /// </summary>
        private readonly DateTime instanceEpoch;

        /// <summary>
        /// Initializes a new instance of the <see cref="ApplicationEnvironment"/> class.
        /// </summary>
        protected internal ApplicationEnvironment()
        {
            this.instanceEpoch = DateTime.UtcNow;
            this.applicationEpoch = this.instanceEpoch;

            string dateTimeFormat = ConfigurationManager.AppSettings[DateTimeFormatKey] ?? DefaultDateTimeFormat;
            string dateTimeValue = ConfigurationManager.AppSettings[DateTimeValueKey];
            if(!string.IsNullOrEmpty(dateTimeValue))
            {
                this.applicationEpoch = DateTime.ParseExact(dateTimeValue, dateTimeFormat, CultureInfo.InvariantCulture);
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ApplicationEnvironment"/> class.
        /// </summary>
        protected internal ApplicationEnvironment(DateTime instanceEpoch, DateTime applicationEpoch)
        {
            this.instanceEpoch = instanceEpoch;
            this.applicationEpoch = applicationEpoch;
        }

        /// <summary>
        /// Gets the current date time.
        /// </summary>
        /// <value>The current date time.</value>
        public DateTime CurrentDateTime
        {
            get { return this.applicationEpoch.AddTicks((DateTime.UtcNow - this.instanceEpoch).Ticks); }
        }

        #endregion
    }
}